package com.taokatao.cardmee;


import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Environment;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.jakewharton.rxbinding.view.RxView;
import com.umeng.analytics.MobclickAgent;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import de.greenrobot.event.EventBus;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;

public class Utils {
    public static boolean DEBUG = true;
    public static String TAG = "app";

    public static int calcStatusBarHeight(Context context) {
        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }

    public static void throttleFirstClick(final View view, final View.OnClickListener l) {
        RxView.clicks(view).throttleFirst(C.settings.ANIMATION_TIME, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Void>() {
                    @Override
                    public void call(Void aVoid) {
                        l.onClick(view);
                    }
                });
    }

    public static void showToast(String text) {
        Context appContext = App.i();
        if (appContext != null) {
            Toast.makeText(appContext, text, android.widget.Toast.LENGTH_SHORT).show();
        }
    }

    public static boolean checkNet() {
        Context appContext = App.i();
        if (appContext != null) {
            try {
                ConnectivityManager connectivity = (ConnectivityManager) App.i().getSystemService(Context.CONNECTIVITY_SERVICE);
                if (connectivity != null) {
                    NetworkInfo info = connectivity.getActiveNetworkInfo();
                    if (info != null && info.isConnected()) {
                        if (info.getState() == NetworkInfo.State.CONNECTED) {
                            return true;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    public static void spWrite(String key, Object value) {
        Context appContext = App.i();
        if (appContext != null) {
            SharedPreferences sp = appContext.getSharedPreferences("app", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sp.edit();
            if (value instanceof String) {
                editor.putString(key, (String) value);
            } else if (value instanceof Double) {
                editor.putString(key, String.valueOf(((Double) value).doubleValue()));
            } else if (value instanceof Integer) {
                editor.putInt(key, (Integer) value);
            } else if (value instanceof Boolean) {
                editor.putBoolean(key, (Boolean) value);
            } else if (value instanceof Float) {
                editor.putFloat(key, (Float) value);
            } else if (value instanceof Long) {
                editor.putLong(key, (Long) value);
            }
            editor.commit();
        }
    }

    public static String spReadString(String key) {
        Context appContext = App.i();
        if (appContext != null) {
            SharedPreferences sp = appContext.getSharedPreferences("app", Context.MODE_PRIVATE);
            return sp.getString(key, "");
        }
        return null;
    }

    public static int spReadInt(String key) {
        return spReadInt(key, 0);
    }

    public static int spReadInt(String key, int defValue) {
        Context appContext = App.i();
        if (appContext != null) {
            SharedPreferences sp = appContext.getSharedPreferences("app", Context.MODE_PRIVATE);
            return sp.getInt(key, defValue);
        }
        return 0;
    }

    public static float spReadFloat(String key) {
        return spReadFloat(key, 0f);
    }

    public static float spReadFloat(String key, float defValue) {
        Context appContext = App.i();
        if (appContext != null) {
            SharedPreferences sp = appContext.getSharedPreferences("app", Context.MODE_PRIVATE);
            return sp.getFloat(key, defValue);
        }
        return 0;
    }

    public static boolean spReadBoolean(String key) {
        return spReadBoolean(key, false);
    }

    public static boolean spReadBoolean(String key, boolean defValue) {
        Context appContext = App.i();
        if (appContext != null) {
            SharedPreferences sp = appContext.getSharedPreferences("app", Context.MODE_PRIVATE);
            return sp.getBoolean(key, defValue);
        }
        return false;
    }

    public static long spReadLong(String key) {
        return spReadLong(key, 0l);
    }

    public static long spReadLong(String key, long defValue) {
        Context appContext = App.i();
        if (appContext != null) {
            SharedPreferences sp = appContext.getSharedPreferences("app", Context.MODE_PRIVATE);
            return sp.getLong(key, defValue);
        }
        return 0;
    }

    public static void logd(String text, Object... args) {
        if (DEBUG && !TextUtils.isEmpty(text)) {
            if (args.length > 0) text = String.format(text, args);
            Log.d(TAG, text);
        }
    }

    public static void loge(String text, Object... args) {
        if (DEBUG && !TextUtils.isEmpty(text)) {
            if (args.length > 0) text = String.format(text, args);
            Log.e(TAG, text);
        }
    }

    public static void postMainThreadBusEvent(int action) {
        logd("postMainThreadBusEvent - action[" + action + "] ");
        EventBus.getDefault().post(new BusEvent(BusEvent.TYPE_MAIN_THREAD, action));
    }

    public static void postMainThreadBusEvent(int action, Object content) {
        logd("postMainThreadBusEvent - action[%s]", action);
        EventBus.getDefault().post(new BusEvent(BusEvent.TYPE_MAIN_THREAD, action, content));
    }

    public static void postMainThreadBusEvent(int action, Object content, Object content2) {
        logd("postMainThreadBusEvent - action[" + action + "] ");
        EventBus.getDefault().post(new BusEvent(BusEvent.TYPE_MAIN_THREAD, action, content, content2));
    }

    public static void hideSoftInputFromWindowAlways(Activity context) {
        logd("hideSoftInputFromWindowAlways[" + Thread.currentThread().getId() + "] " + context.getClass().getSimpleName() + " currFocus:" + context.getCurrentFocus());
        if (context.getCurrentFocus() != null) {
            ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(context.getCurrentFocus()
                    .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    public static boolean isDarkColorTheme(int styleColor) {
        int r = Color.red(styleColor);
        int g = Color.green(styleColor);
        int b = Color.blue(styleColor);
        float grayLevel = r * 0.299f + g * 0.587f + b * 0.114f;
        return grayLevel < 192; // default -> 192
    }

    /**
     * 得到imes号
     */
    public static String getImei(Context appContext) {
        String imei = spReadString("imei");
        if (!TextUtils.isEmpty(imei)) {
            return imei;
        }

        try {
            TelephonyManager mTelephonyMgr = (TelephonyManager) appContext.getSystemService(Context.TELEPHONY_SERVICE);
            imei = mTelephonyMgr.getDeviceId();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (TextUtils.isEmpty(imei) || imei.length() < 10) {
                imei = UUID.randomUUID().toString();
            }
            spWrite("imei", imei);
        }
        return imei;
    }


    public static String formatCardCode(String originalValue) {
        if (originalValue == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < originalValue.length(); i++) {
            if (i % 3 == 0) {
                sb.append(" ");
            }
            sb.append(originalValue.charAt(i));
        }
        return sb.toString().trim();
    }

    public static String formatColor(int color) {
        String R, G, B;
        StringBuffer sb = new StringBuffer();
        R = Integer.toHexString(Color.red(color));
        G = Integer.toHexString(Color.green(color));
        B = Integer.toHexString(Color.blue(color));
        R = R.length() == 1 ? "0" + R : R;
        G = G.length() == 1 ? "0" + G : G;
        B = B.length() == 1 ? "0" + B : B;
        sb.append("#");
        sb.append(R.toUpperCase());
        sb.append(G.toUpperCase());
        sb.append(B.toUpperCase());
        return sb.toString();
    }

    /**
     * 流转字符串
     */
    public static String inputStreamToString(InputStream tInputStream) {
        if (tInputStream != null) {
            try {
                BufferedReader tBufferedReader = new BufferedReader(new InputStreamReader(tInputStream));
                StringBuffer tStringBuffer = new StringBuffer();
                String sTempOneLine;
                while ((sTempOneLine = tBufferedReader.readLine()) != null) {
                    tStringBuffer.append(sTempOneLine);
                }
                return tStringBuffer.toString();
            } catch (Exception ex) {
                ex.printStackTrace();
                try {
                    tInputStream.close();
                } catch (IOException ignored) {
                }
            }
        }
        return null;
    }

    /**
     * 状态栏文字颜色 以及伪状栏高度调节
     */
    public static final void fitSysWindowAndSetStatusBarMode(int styleColor, View vFit) {
        if (vFit == null) {
            loge("fitSysWindowAndSetStatusBarMode vFit is null");
            return;
        }

        boolean specialStatusBarFlag = false;
        final boolean darkMode = !isDarkColorTheme(styleColor);
        final Window window = ((Activity) vFit.getContext()).getWindow();

        if ("Xiaomi".equalsIgnoreCase(Build.BRAND)) {
            Class<? extends Window> clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                extraFlagField.invoke(window, darkMode ? darkModeFlag : 0, darkModeFlag);
                logd("Xiaomi fitSysWindowAndSetStatusBarMode: success");
                specialStatusBarFlag = true;
            } catch (Exception e) {
                e.printStackTrace();
                loge("Xiaomi fitSysWindowAndSetStatusBarMode: failed");
                specialStatusBarFlag = false;
            }
        } else if ("MeiZu".equalsIgnoreCase(Build.BRAND)) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (darkMode) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                logd("MeiZu fitSysWindowAndSetStatusBarMode: success");
                specialStatusBarFlag = true;
            } catch (Exception e) {
                e.printStackTrace();
                loge("MeiZu fitSysWindowAndSetStatusBarMode: failed");
                specialStatusBarFlag = false;
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            final int statusBarHeight = calcStatusBarHeight(vFit.getContext());
            vFit.getLayoutParams().height = statusBarHeight;
        }

        if (specialStatusBarFlag) {
            vFit.setBackgroundColor(styleColor);
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                // 部分机型的statusBar会有半透明的黑色背景
                window.setStatusBarColor(Color.TRANSPARENT);
            }

//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//                // http://blog.csdn.net/brian512/article/details/52096445
//                // 状态栏字体设置为深色，SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 为SDK23增加
//                loge("Android6.0 fitSysWindowAndSetStatusBarMode setSystemUiVisibility View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR");
//                Utils.showToast("Android6.0 fitSysWindowAndSetStatusBarMode setSystemUiVisibility View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR");
//                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
//            } else {
//                loge("fitSysWindowAndSetStatusBarMode setStatusBarBackgroundColor R.color.colorPrimaryDark");
//                vFit.setBackgroundColor(colorBurn(styleColor));
//            }

            // 就差一台6.0的Android真机了
            int topColor = styleColor != Color.TRANSPARENT ? colorBurn(styleColor) : Color.TRANSPARENT;
            logd("fitSysWindowAndSetStatusBarMode setTopColor %d", topColor);
            vFit.setBackgroundColor(topColor);
        }
    }


    /**
     * 颜色加深处理
     *
     * @param RGBValues RGB的值，由alpha（透明度）、red（红）、green（绿）、blue（蓝）构成，
     *                  Android中我们一般使用它的16进制，
     *                  例如："#FFAABBCC",最左边到最右每两个字母就是代表alpha（透明度）、
     *                  red（红）、green（绿）、blue（蓝）。每种颜色值占一个字节(8位)，值域0~255
     *                  所以下面使用移位的方法可以得到每种颜色的值，然后每种颜色值减小一下，在合成RGB颜色，颜色就会看起来深一些了
     * @return
     */
    public static int colorBurn(int RGBValues) {
        int alpha = RGBValues >> 24;
        int red = RGBValues >> 16 & 0xFF;
        int green = RGBValues >> 8 & 0xFF;
        int blue = RGBValues & 0xFF;
        red = (int) Math.floor(red * (1 - 0.1));
        green = (int) Math.floor(green * (1 - 0.1));
        blue = (int) Math.floor(blue * (1 - 0.1));
        return Color.rgb(red, green, blue);
    }


    /**
     * 保存图片到指定目录
     *
     * @param bmp      位图对象
     * @param filepath 保存地址
     * @return 操作结果
     */
    public static boolean saveImage(Bitmap bmp, String filepath) {
        try {
            File saveFile = new File(filepath);
            if (!saveFile.exists()) saveFile.createNewFile();
            OutputStream stream = new BufferedOutputStream(new FileOutputStream(saveFile.getAbsolutePath()));
            Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
            int quality = 100;
            bmp.compress(format, quality, stream);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean saveFile(String content, String filepath) {
        FileWriter fw = null;
        BufferedWriter writer = null;
        try {
            File file = new File(filepath);
            if (!file.exists()) file.createNewFile();
            writer = new BufferedWriter(fw = new FileWriter(file));
            writer.write(content);
            writer.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (writer != null) writer.close();
                if (fw != null) fw.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * 用于将给定的内容生成成一维码 注：目前生成内容为中文的话将直接报错，要修改底层jar包的内容
     *
     * @param content 将要生成一维码的内容
     * @return 返回生成好的一维码bitmap
     * @throws WriterException WriterException异常
     */
    public static Bitmap createBarcode(String content) throws WriterException {
        // 生成一维条码,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
        BitMatrix matrix = new MultiFormatWriter().encode(content,
                BarcodeFormat.CODE_128, 500, 200);
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (matrix.get(x, y)) {
                    pixels[y * width + x] = 0xff000000;
                }
            }
        }

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        // 通过像素数组生成bitmap,具体参考api
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 用字符串生成二维码
     *
     * @param text 将要生成一维码的内容
     * @return 返回生成好的一维码bitmap
     * @throws WriterException WriterException异常
     */
    public static Bitmap createQRCode(String text) throws WriterException {
        //生成二维矩阵,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        BitMatrix matrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, 400, 400, hints);
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        //二维矩阵转为一维像素数组,也就是一直横着排了
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (matrix.get(x, y)) {
                    pixels[y * width + x] = 0xff000000;
                } else {
                    pixels[y * width + x] = 0xffffffff;
                }
            }
        }
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        //通过像素数组生成bitmap,具体参考api
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    public static int getAppVersionCode() {
        Context appContext = App.i();
        if (appContext != null) {
            try {
                int versionCode = appContext.getPackageManager().getPackageInfo(appContext.getPackageName(), 0).versionCode;
                logd("Utils getAppVersionCode %d", versionCode);
                return versionCode;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    public static String getAppVersionName() {
        Context appContext = App.i();
        if (appContext != null) {
            try {
                String versionName = appContext.getPackageManager().getPackageInfo(appContext.getPackageName(), 0).versionName;
                logd("Utils getAppVersionCode %s", versionName);
                return versionName;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    public static void onMobEvent(Context context, String event, String[] keys, String[] values) {
        if (!TextUtils.isEmpty(event)) {
            if (keys != null && values != null && keys.length == values.length) {
                if (keys.length < 1) {
                    onMobEvent(context, event);
                } else {
                    Map<String, String> map = new HashMap<>();
                    for (int i = 0; i < keys.length; i++) {
                        String mValue = values[i];
                        if (!TextUtils.isEmpty(mValue)) {
                            if (mValue.length() > 255) {
                                mValue = mValue.substring(0, 255);
                            }
                            map.put(keys[i], mValue);
                        }
                    }
                    if (map.keySet() != null && map.keySet().size() > 0) {
                        Utils.logd("Utils onMobEvent %s ", event);
                        MobclickAgent.onEvent(context, event, map);
                    } else {
                        Utils.logd("Utils onMobEvent %s", event);
                        MobclickAgent.onEvent(context, event);
                    }
                }
            }
        }
    }

    public static void onMobEvent(Context context, String event) {
        if (!TextUtils.isEmpty(event)) {
            Utils.logd("Utils onMobEvent %s", event);
            MobclickAgent.onEvent(context, event);
        }
    }

    public static String recordCrashInfo(Context context, Throwable throwable) {
        HashMap<String, String> mapSimpleInfo = new HashMap<>();
        PackageManager mPackageManager = context.getPackageManager();
        PackageInfo mPackageInfo = null;
        try {
            mPackageInfo = mPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
            mapSimpleInfo.put("versionName", mPackageInfo.versionName);
            mapSimpleInfo.put("versionCode", String.valueOf(mPackageInfo.versionCode));
            mapSimpleInfo.put("MODEL", Build.MODEL);
            mapSimpleInfo.put("SDK_INT", String.valueOf(Build.VERSION.SDK_INT));
            mapSimpleInfo.put("PRODUCT", Build.PRODUCT);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        String fileName = null;
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : mapSimpleInfo.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key).append(" = ").append(value).append("\n");
        }

        StringWriter mStringWriter = new StringWriter();
        PrintWriter mPrintWriter = new PrintWriter(mStringWriter);
        throwable.printStackTrace(mPrintWriter);
        mPrintWriter.close();
        sb.append(mStringWriter.toString());

        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File dir = new File(context.getExternalCacheDir().getAbsolutePath() + File.separator + "crash" + File.separator);
            if (!dir.exists()) dir.mkdir();

            System.setProperty("user.timezone", "Asia/Shanghai");
            TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
            TimeZone.setDefault(tz);
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

            try {
                fileName = dir.toString() + File.separator + format.format(new Date(System.currentTimeMillis())) + ".txt";
                FileOutputStream fos = new FileOutputStream(fileName);
                fos.write(sb.toString().getBytes());
                fos.flush();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return fileName;
    }


    public static void recordInfo(Context context, String content) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            if (context == null || context.getExternalCacheDir() == null) return;
            File dir = new File(context.getExternalCacheDir().getAbsolutePath() + File.separator + "record" + File.separator);
            if (!dir.exists()) dir.mkdir();

            System.setProperty("user.timezone", "Asia/Shanghai");
            TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
            TimeZone.setDefault(tz);
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

            try {
                String fileName = dir.toString() + File.separator + format.format(new Date(System.currentTimeMillis())) + ".txt";
                FileOutputStream fos = new FileOutputStream(fileName);
                fos.write(content.getBytes());
                fos.flush();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}
